package com.zj.utils.view.dialog

import android.app.Dialog
import android.content.Context
import android.hardware.Sensor
import android.hardware.SensorEvent
import android.hardware.SensorEventListener
import android.hardware.SensorManager
import android.location.Criteria
import android.os.Bundle
import android.os.Handler
import android.text.TextUtils
import android.view.View
import android.view.ViewGroup
import android.view.animation.AccelerateInterpolator
import android.widget.Button
import android.widget.ImageView
import android.widget.LinearLayout
import android.widget.TextView
import com.zj.utils.R
import com.zj.utils.view.CompassView
import kotlinx.android.synthetic.main.compass_dialog_layout.*
import java.util.*

/**
 * <pre>
 *     author : luhenchang
 *     e-mail : 1276998208@qq.com
 *     time   : 2020/03/25
 *     desc   : 版权所有
 *     version: 1.0
 * </pre>
 */
class CompassDialog(context: Context) : Dialog(context) {
    constructor(context: Context,compassInterface: CompassInterface) : this(context) {
        mcompassListener=compassInterface
    }
    private var value1: String=""
    private var value2: String=""
    private var value3: String=""
    private var bearingString=""
    private val MAX_ROATE_DEGREE = 1.0f
    private var mSensorManager: SensorManager? = null
    private var mOrientationSensor: Sensor? = null
    private var mPressureSensor: Sensor? = null
    private var mDirection = 0f
    private var mTargetDirection = 0f
    private var mInterpolator: AccelerateInterpolator? = null
    protected val mHandler = Handler()
    private var mStopDrawing = false
    private var mChinease = false

    var mCompassView: View? = null
    var mPointer: CompassView? = null
    var mAltitudeTextView: TextView? = null
    var mPressureTextView: TextView? = null
    var mDirectionLayout: LinearLayout? = null
    var mAngleLayout: LinearLayout? = null
    var mcompassListener:CompassInterface?=null
    var mSureButton: Button? =null

    protected var mCompassViewUpdater: Runnable = object : Runnable {
        override fun run() {
            if (mPointer != null && !mStopDrawing) {
                if (mDirection != mTargetDirection) {

                    // calculate the short routine
                    var to = mTargetDirection
                    if (to - mDirection > 180) {
                        to -= 360f
                    } else if (to - mDirection < -180) {
                        to += 360f
                    }

                    // limit the max speed to MAX_ROTATE_DEGREE
                    var distance = to - mDirection
                    if (Math.abs(distance) > MAX_ROATE_DEGREE) {
                        distance = if (distance > 0) MAX_ROATE_DEGREE else -1.0f * MAX_ROATE_DEGREE
                    }
                    // need to slow down if the distance is short
                    mDirection = normalizeDegree(mDirection
                            + (to - mDirection) * mInterpolator!!.getInterpolation(if (Math
                                    .abs(distance) > MAX_ROATE_DEGREE) 0.4f else 0.3f))
                    mPointer!!.updateDirection(mDirection)
                }
                updateDirection()
                mHandler.postDelayed(this, 20)
            }
        }
    }
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(R.layout.compass_dialog_layout)
        initResources()
        initServices()
    }

    override fun onStart() {
        super.onStart()
        if (mOrientationSensor != null) {
            mSensorManager!!.registerListener(mOrientationSensorEventListener, mOrientationSensor, SensorManager.SENSOR_DELAY_GAME)
        }
        if (mPressureSensor != null) {
            mSensorManager!!.registerListener(mPressureSensorEventListener, mPressureSensor,
                    SensorManager.SENSOR_DELAY_GAME)
        }
        mStopDrawing = false
        mHandler.postDelayed(mCompassViewUpdater, 20)
    }

    override fun onStop() {
        super.onStop()
        mStopDrawing = true
        if (mOrientationSensor != null) {
            mSensorManager!!.unregisterListener(mOrientationSensorEventListener)
        }
        if (mPressureSensor != null) {
            mSensorManager!!.unregisterListener(mPressureSensorEventListener)
        }
    }
    private fun initResources() {
        mDirection = 0.0f
        mTargetDirection = 0.0f
        mInterpolator = AccelerateInterpolator()
        mStopDrawing = true
        mChinease = TextUtils.equals(Locale.getDefault().language, "zh")
        mCompassView = findViewById(R.id.view_compass)
        mPointer = findViewById(R.id.compass_pointer)
        mAltitudeTextView = findViewById(R.id.textview_altitude)
        mPressureTextView = findViewById(R.id.textview_pressure)
        mDirectionLayout = findViewById(R.id.layout_direction)
        mSureButton=findViewById(R.id.map_btn_add)
        mAngleLayout = findViewById<View>(R.id.layout_angle) as LinearLayout
        mPointer!!.setImageResource(if (mChinease) R.mipmap.compass_cn else R.mipmap.compass)
        mSureButton?.setOnClickListener {
            mcompassListener?.Result(value1+value2+value3)
            this.dismiss()
        }
        map_btn_cancel.setOnClickListener {
            this.dismiss()
        }
    }
    private fun initServices() {
        // sensor manager
        mSensorManager = context.getSystemService(Context.SENSOR_SERVICE) as SensorManager
        mOrientationSensor = mSensorManager?.getDefaultSensor(Sensor.TYPE_ORIENTATION)
        mPressureSensor = mSensorManager?.getDefaultSensor(Sensor.TYPE_PRESSURE)
        // location manager
        val criteria = Criteria()
        criteria.accuracy = Criteria.ACCURACY_FINE
        criteria.isAltitudeRequired = false
        criteria.isBearingRequired = false
        criteria.isCostAllowed = true
        criteria.powerRequirement = Criteria.POWER_LOW
    }

    private fun updateDirection() {
        val lp = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        mDirectionLayout!!.removeAllViews()
        bearingString=""
        mAngleLayout!!.removeAllViews()
        var east: ImageView? = null
        var west: ImageView? = null
        var south: ImageView? = null
        var north: ImageView? = null
        val direction = normalizeDegree(mTargetDirection * -1.0f)
        if (direction > 22.5f && direction < 157.5f) {
            // east
            east = ImageView(context)
            east.setImageResource(if (mChinease) R.mipmap.e_cn else R.mipmap.e)
            east.layoutParams = lp
        } else if (direction > 202.5f && direction < 337.5f) {
            // west
            west = ImageView(context)
            west.setImageResource(if (mChinease) R.mipmap.w_cn else R.mipmap.w)
            west.layoutParams = lp
        }
        if (direction > 112.5f && direction < 247.5f) {
            // south
            south = ImageView(context)
            south.setImageResource(if (mChinease) R.mipmap.s_cn else R.mipmap.s)
            south.layoutParams = lp
        } else if (direction < 67.5 || direction > 292.5f) {
            // north
            north = ImageView(context)
            north.setImageResource(if (mChinease) R.mipmap.n_cn else R.mipmap.n)
            north.layoutParams = lp
        }
        /* if (mChinease) {
             // east/west should be before north/south
             if (east != null) {
                 bearingString+=context.getString(R.string.east)
                 mDirectionLayout!!.addView(east)
             }
             if (west != null) {
                 bearingString+=context.getString(R.string.west)
                 mDirectionLayout!!.addView(west)
             }
             if (south != null) {
                 bearingString+=context.getString(R.string.south)
                 mDirectionLayout!!.addView(south)
             }
             if (north != null) {
                 bearingString+=context.getString(R.string.north)
                 mDirectionLayout!!.addView(north)
             }
         } else {
             if (south != null) {
                 bearingString+=context.getString(R.string.south)
                 mDirectionLayout!!.addView(south)
             }
             if (north != null) {
                 bearingString+=context.getString(R.string.north)
                 mDirectionLayout!!.addView(north)
             }
             if (east != null) {
                 bearingString+=context.getString(R.string.east)
                 mDirectionLayout!!.addView(east)
             }
             if (west != null) {
                 bearingString+=context.getString(R.string.west)
                 mDirectionLayout!!.addView(west)
             }
         }*/
        var direction2 = direction.toInt()
        var show = false
        value1=""
        value2=""
        value3=""
        if (direction2 >= 100) {
            value1=(direction2 / 100).toString()
            mAngleLayout!!.addView(getNumberImage(direction2 / 100))
            direction2 %= 100
            show = true
        }
        if (direction2 >= 10 || show) {
            if(value1 == "3") {
                if( (direction2 / 10)<=60) {
                    value2 = (direction2 / 10).toString()
                }else{
                    value2="2"
                }
            }else{
                value2 = (direction2 / 10).toString()
            }
            mAngleLayout!!.addView(getNumberImage(direction2 / 10))
            direction2 %= 10
        }
        value3=(direction2).toString()
        mAngleLayout!!.addView(getNumberImage(direction2))
        val degreeImageView = ImageView(context)
        degreeImageView.setImageResource(R.mipmap.degree)
        degreeImageView.layoutParams = lp
        mAngleLayout!!.addView(degreeImageView)
    }

    private fun getNumberImage(number: Int): ImageView? {
        val image = ImageView(context)
        val lp = ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT, ViewGroup.LayoutParams.WRAP_CONTENT)
        when (number) {
            0 -> image.setImageResource(R.mipmap.number_0)
            1 -> image.setImageResource(R.mipmap.number_1)
            2 -> image.setImageResource(R.mipmap.number_2)
            3 -> image.setImageResource(R.mipmap.number_3)
            4 -> image.setImageResource(R.mipmap.number_4)
            5 -> image.setImageResource(R.mipmap.number_5)
            6 -> image.setImageResource(R.mipmap.number_6)
            7 -> image.setImageResource(R.mipmap.number_7)
            8 -> image.setImageResource(R.mipmap.number_8)
            9 -> image.setImageResource(R.mipmap.number_9)
        }
        image.layoutParams = lp
        return image
    }

    private val mOrientationSensorEventListener: SensorEventListener = object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent) {
            val direction = event.values[0] * -1.0f
            mTargetDirection = normalizeDegree(direction)
        }

        override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
    }

    private val mPressureSensorEventListener: SensorEventListener = object : SensorEventListener {
        override fun onSensorChanged(event: SensorEvent) {
            mAltitudeTextView?.setText(context.getString(R.string.altitude, calculateAltitude(event.values[0]).toInt()))
            mPressureTextView?.setText(context.getString(R.string.pressure, event.values[0] / 10))
        }

        override fun onAccuracyChanged(sensor: Sensor, accuracy: Int) {}
    }

    private fun calculateAltitude(pressure: Float): Float {
        val sp = 1013.25f //standard pressure
        return (sp - pressure) * 100.0f / 12.7f
    }

    private fun normalizeDegree(degree: Float): Float {
        return (degree + 720) % 360
    }
}